// Copyright 2021 Guoyoko. All Rights Reserved.


#include "Graph/CustomizeFlowGraphSchema.h"
#include "Graph/CustomizeFlowGraphNode.h"
#include "ToolMenu.h"
#include "Framework/Commands/GenericCommands.h"
#include "GraphEditorActions.h"
#include "Graph/CustomizeFlowGraphNode_Root.h"
#include "Graph/CustomizeFlowGraphNode.h"
#include "CustomizeFlowEditor.h"


#define LOCTEXT_NAMESPACE "CustomizeFlowGraphSchema"


void UCustomizeFlowGraphSchema::CreateDefaultNodesForGraph(UEdGraph& Graph) const
{
	FGraphNodeCreator<UCustomizeFlowGraphNode_Root> NodeCreator(Graph);
	UCustomizeFlowGraphNode_Root* RootNode = NodeCreator.CreateNode();
	NodeCreator.Finalize();
	SetNodeMetaData(RootNode, FNodeMetadata::DefaultGraphNode);
}

void UCustomizeFlowGraphSchema::GetGraphContextActions(FGraphContextMenuBuilder& ContextMenuBuilder) const
{
	FCustomizeFlowEditorModule& EditorModule = FModuleManager::GetModuleChecked<FCustomizeFlowEditorModule>(TEXT("CustomizeFlowEditor"));
	EditorModule.CreateClassCache();
	FCusFlowGraphNodeClassHelper* ClassCache = EditorModule.GetClassCache().Get();

	TArray<FCusFlowGraphNodeClassData> NodeClasses;
	ClassCache->GatherClasses(UCustomizeFlowFlowTaskNode::StaticClass(), NodeClasses);

	for (const auto& NodeClass : NodeClasses)
	{
		const FText NodeTypeName = FText::FromString(FName::NameToDisplayString(NodeClass.ToString(), false));

		TSharedPtr<FEdGraphSchemaAction_NewNode> Action(new FEdGraphSchemaAction_NewNode(FText::GetEmpty(), FText::FromString("New Action"), LOCTEXT("AddStateTooltip", "A new state node"), 0));
		UCustomizeFlowGraphNode* OpNode = NewObject<UCustomizeFlowGraphNode>(ContextMenuBuilder.OwnerOfTemporaries);
		OpNode->ClassData = NodeClass;
		Action->NodeTemplate = OpNode;
		ContextMenuBuilder.AddAction(Action);
	}
}

const FPinConnectionResponse UCustomizeFlowGraphSchema::CanCreateConnection(const UEdGraphPin* PinA, const UEdGraphPin* PinB) const
{
	// Make sure the pins are not on the same node
	if (PinA->GetOwningNode() == PinB->GetOwningNode())
	{
		return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, TEXT("Both are on the same node"));
	}

	// Compare the directions
	if ((PinA->Direction == EGPD_Input) && (PinB->Direction == EGPD_Input))
	{
		return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorInput", "Can't connect input node to input node"));
	}
	else if ((PinA->Direction == EGPD_Output) && (PinB->Direction == EGPD_Output))
	{
		return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinErrorOutput", "Can't connect output node to output node"));
	}

	UCustomizeFlowGraphNode_Root* pEdNode_RootA = Cast<UCustomizeFlowGraphNode_Root>(PinA->GetOwningNode());
	UCustomizeFlowGraphNode_Root* pEdNode_RootB = Cast<UCustomizeFlowGraphNode_Root>(PinA->GetOwningNode());
	UCustomizeFlowGraphNode* pEdNode_A = Cast<UCustomizeFlowGraphNode>(PinA->GetOwningNode());
	UCustomizeFlowGraphNode* pEdNode_B = Cast<UCustomizeFlowGraphNode>(PinB->GetOwningNode());

	if (pEdNode_RootA || pEdNode_RootB)
	{
		if (pEdNode_RootA && pEdNode_B)
		{
			return FPinConnectionResponse(CONNECT_RESPONSE_BREAK_OTHERS_A, TEXT(""));
		}
		if (pEdNode_RootB && pEdNode_A)
		{
			return FPinConnectionResponse(CONNECT_RESPONSE_BREAK_OTHERS_B, TEXT(""));
		}
		return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, TEXT("Entry must connect to a flow node"));
	}

	if (pEdNode_A == nullptr || pEdNode_B == nullptr)
	{
		return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, LOCTEXT("PinError", "Not a valid USelfGraphNode"));
	}

	return FPinConnectionResponse(CONNECT_RESPONSE_BREAK_OTHERS_AB, LOCTEXT("PinConnect", "Connect nodes with edge"));
}

#undef LOCTEXT_NAMESPACE

